"use strict";

/**
 * 业务工具类，提供了一些业务相关的公用方法
 */
let ETool = function () {
    let util = EUtil;
    let app = EApp;
    // 默认设置

    // `controller` 的 `@RequestMapping` 根路径
    let baseUrl = null;

    /**
     * 获取表单中`class`包含`auto-params`的元素，返回url所需的参数格式
     *
     * @param element {element} html 元素对象（必要）
     * @returns {string|null} eg: a=1&b=2
     */
    let getAutoParams = function (element) {
        if (typeof element !== 'undefined') {
            return $(element).parents('.e-form').find('.auto-params').serialize();
        } else {
            return null;
        }
    };

    /**
     * 验证url是否为空,如为空根据（method）默认规则生成
     *
     * @param url {string|null} url
     * @param method {string} 方法名（必要）
     * @param suffix {string|null} 后缀
     * @returns {string|null} 处理后的url
     */
    let getUrl = function (url, method, suffix) {
        if (util.isBlank(url)) {
            if (checkBaseUrl()) {
                url = baseUrl + urlSuffix[method] + (util.isNotBlank(suffix) ? suffix : '');
            } else {
                return null;
            }
        }
        return url;
    };

    /**
     * 检查业务通用url部分是否已设置
     *
     * @returns {boolean} true/false
     */
    let checkBaseUrl = function () {
        if (util.isNotBlank(baseUrl)) {
            return true;
        } else {
            printWarn('请使用ETool.setBaseUrl(\'string\');设置业务url根目录');
            return false;
        }
    };

    /**
     * 获取操作按钮class
     *
     * @param type {string} 按钮类型 eg：success、info、warning、danger、brand、dark、light  (默认：success)
     * @returns {string} class
     */
    let getActionsBtnClass = function (type) {
        if (util.isBlank(type)) {
            type = 'success';
        }
        return 'table-actions btn btn-sm btn-icon btn-icon-md btn-light-hover-' + type;
    };

    /**
     * 根据用户偏好设置判断是否使用弹框提示
     *
     * @returns {boolean} true/false
     */
    let useSimpleTip = function () {
        let simpleTip = true;
        let cacheSettings = ETool.getCache('preference-settings');
        if (EUtil.isNotBlank(cacheSettings)) {
            simpleTip = $.parseJSON(cacheSettings)['simpleTip'];
        }
        return simpleTip;
    };
    /**
     * 输出警告信息（限调试模式）
     *
     * @param str {string} 警告信息（必要）
     */
    let printWarn = function (str) {
        if (EDebug) {
            console.warn(str);
        }
    };

    return {
        /**
         * 设置业务 base url
         *
         * @param url {string} 访问地址（必要）
         */
        setBaseUrl: function (url) {
            baseUrl = url;
        },

        /**
         * 获取业务 base url
         *
         * @return {string} 业务 base url
         */
        getBaseUrl: function () {
            return baseUrl;
        },

        /**
         * 打开导入页面
         *
         * @param importCode {string} `系统管理>系统设置>导入模板中的模板代码`（必要）
         */
        importData: function (importCode) {
            app.openPage('导入数据', basePath + '/auth/sys/import/excel/data/' + importCode);
        },

        /**
         * 导出数据
         *
         * @param element {element} html 元素对象（必要）
         * @param url {string|null} 请求地址 (默认：规则生成)
         */
        exportData: function (element, url) {
            util.setButtonWait(element);
            let $form = $(element).parents('.e-form');
            if (util.isBlank(url)) {
                // 检查&获取请求地址
                url = getUrl(url, 'exportData', null);
                if (util.isBlank(url)) {
                    util.offButtonWait(element);
                    return;
                }
            }
            if (url.indexOf('?') > -1) {
                url += '&' + $form.serialize()
            } else {
                url += '?' + $form.serialize()
            }
            // 下载文件
            ETool.downloadFile(url);
            util.offButtonWait(element);
        },

        /**
         * 保存数据，一般用于表单页面
         *
         * @param element {element} html 元素对象 （必要）
         * @param url {string|null} 请求地址 （默认：规则生成）
         * @param needAlert {boolean|null} 是否需要弹出处理结果提示 （默认：true）
         * @param needValidate {boolean|null} 是否需要表单验证 （默认：true）
         * @param callback {function|null} 回调函数
         */
        saveData: function (element, url, needAlert, needValidate, callback) {
            if (needAlert == null) needAlert = true;
            if (needValidate == null) needValidate = true;
            let $form = $(element).parents('.e-form');
            // 如果不需要验证或者表单验证通过
            if (!needValidate || $form.valid()) {
                util.setButtonWait(element);
                if ($form != null && $form.length > 0) {
                    if (util.isBlank(url)) {
                        // 检查&获取请求地址
                        url = getUrl(url, 'saveData', null);
                        if (util.isBlank(url)) {
                            util.offButtonWait(element);
                            return;
                        }
                    }
                    // 保存
                    util.ajax({
                        url: url,
                        data: $form.serialize(),
                        error: function (XMLHttpRequest, textStatus, errorThrown) {
                            util.offButtonWait(element);
                            util.ajaxErrorCallback(XMLHttpRequest, textStatus, errorThrown);
                        },
                        fail: function () {
                            util.offButtonWait(element);
                        },
                        success: function (res) {
                            util.offButtonWait(element);
                            if (needAlert) {
                                let $id = $form.find('#id');
                                if ($id != null && $id.length > 0) {
                                    // 根据表单中`#id`的value属性判断是新增还是修改
                                    if (util.isBlank($id.val())) {
                                        ETool.successTip(commonTips.success, commonTips.save.add);
                                        $id.val(res.data.id);
                                    } else {
                                        ETool.successTip(commonTips.success, commonTips.save.update);
                                    }
                                } else {
                                    ETool.successTip(commonTips.success, commonTips.save.default);
                                }
                            }
                            if (util.isFunction(callback)) {
                                callback(res);
                            }
                        }
                    });
                } else {
                    printWarn('ETool.saveData() -> 缺少表单元素');
                }
            }
        },

        /**
         * 保存并关闭，注: 方法不支持回调函数
         *
         * @param element {element} html 元素对象（必要）
         * @param url {string|null} 请求地址 (默认：规则生成)
         * @param needAlert {boolean|null} 是否需要弹出处理结果提示 (默认：true)
         * @param needValidate {boolean|null} 是否需要表单验证 (默认：true)
         */
        saveAndClose: function (element, url, needAlert, needValidate) {
            ETool.saveData(element, url, needAlert, needValidate, function () {
                app.closeCurrentPage();
            });
        },

        /**
         * 打开新增页面，在列表页中使用，调用前请确保设置了`baseUrl`变量
         *
         * @param element {element} element元素（必要）
         * @param name {string|null} tab页名称 （默认: 新增数据）
         * @param url {string|null} 请求地址，用于自定义保存url （默认：规则生成）
         * @param pId {string|null} 父Id，用于需要在url后拼接 `/add/pId`场景
         */
        addData: function (element, name, url, pId) {
            if (typeof element !== 'undefined') {
                util.setButtonWait(element);
            }
            // 检查&获取请求地址
            if (util.isBlank(url)) {
                url = getUrl(url, 'add', pId);
                if (util.isBlank(url)) return;
            }
            // 获取页面中需要添加到url后的参数
            let params = getAutoParams(element);
            if (util.isNotBlank(params)) {
                url += '?' + params;
            }
            // 标签页名称
            if (util.isBlank(name)) {
                name = $(element).text();
                if (util.isBlank(name)) {
                    name = '新增数据';
                } else {
                    name = name.trim();
                }
            }
            app.openPage(name, url);
            if (typeof element !== 'undefined') {
                util.offButtonWait(element);
            }
        },

        /**
         * 根据数据id删除数据，一般用于表格最后操作列
         *
         * @param element {element} html 元素对象（必要）
         * @param id {string} 要删除数据的id（必要）
         * @param url {string|null} 请求地址，用于自定义删除url （默认：规则生成）
         * @param needAlert {boolean|null} 是否需要弹出处理结果提示 （默认：true）
         * @param callback {function|null} 回调函数
         */
        deleteById: function (element, id, url, needAlert, callback) {
            util.alertConfirm(commonTips.delete.title, commonTips.delete.subtitle, function () {
                if (typeof needAlert === 'undefined') needAlert = true;
                let row = $(element).parents('tr.e-datatable__row');
                let $dataTable = $(element).parents('.e-form').find('.e-datatable');
                // 检查&获取请求地址
                if (util.isBlank(url)) {
                    url = getUrl(url, 'deleteById', id);
                    if (util.isBlank(url)) return;
                }
                util.ajax({
                    wait: row,
                    url: url,
                    success: function (res) {
                        // 弹出提示
                        if (needAlert) {
                            ETool.successTip(commonTips.success, commonTips.delete.success);
                        }
                        // 刷新数据
                        ETool.selectData(element);
                        // 回调函数
                        if (util.isFunction(callback)) {
                            callback(res);
                        }
                    }
                });
            });
        },

        /**
         * 删除数据，用于列表页删除数据，支持单个或批量操作
         *
         * @param element {element} html 元素对象（必要）
         * @param id {string|null} 要删除的id，如果为空则从表格中获取勾选的数据（默认：获取表格中勾选的数据）
         * @param url {string|null} 请求地址，用于自定义删除url（默认：规则生成）
         * @param needAlert {boolean|null} 是否需要弹出处理结果提示（默认：true）
         * @param callback {function|null}  回调函数
         */
        deleteData: function (element, id, url, needAlert, callback) {
            let $dataTable = $(element).parents('.e-form').find('.e-datatable');
            // 检查&获取数据id
            if (util.isBlank(id)) {
                if (typeof $dataTable !== 'undefined' && $dataTable.length > 0) {
                    // 从表格中获取已选中select
                    let ids = ETool.getSelectData($dataTable);
                    if (ETool.checkSelectDataIsNotEmpty(ids, true)) {
                        id = ids.join(',');
                    } else {
                        return;
                    }
                } else {
                    printWarn('无法获取要删除的数据id');
                    return;
                }
            }
            // 询问
            util.alertConfirm(commonTips.delete.title, commonTips.delete.subtitle, function () {
                // 禁用按钮
                util.setButtonWait(element);
                if (typeof needAlert === 'undefined') needAlert = true;
                // 检查&获取请求地址
                if (util.isBlank(url)) {
                    url = getUrl(url, 'deleteById', id);
                    if (util.isBlank(url)) {
                        util.offButtonWait(element);
                        return;
                    }
                }

                util.ajax({
                    url: url,
                    wait: $dataTable,
                    error: function (XMLHttpRequest, textStatus, errorThrown) {
                        util.offButtonWait(element);
                        util.ajaxErrorCallback(XMLHttpRequest, textStatus, errorThrown);
                    },
                    fail: function () {
                        util.offButtonWait(element);
                    },
                    success: function (res) {
                        util.offButtonWait(element);
                        // 弹出提示
                        if (needAlert) {
                            ETool.successTip(commonTips.success, commonTips.delete.success);
                        }
                        // 刷新数据
                        ETool.selectData(element);
                        // 回调函数
                        if (util.isFunction(callback)) {
                            callback(res);
                        }
                    }
                });
            });
        },

        /**
         * 根据数据id修改数据，一般用于表格最后操作列
         *
         * @param element {element} html 元素对象（必要）
         * @param id {string} 要修改数据的id（必要）
         * @param name {string|null} tab页名称（默认: 修改）
         * @param url {string|null} 请求地址，用于自定义修改url （默认：规则生成）
         * @param callback {function|null} 回调函数
         */
        editById: function (element, id, name, url, callback) {
            url = getUrl(url, 'input', id);
            if (util.isBlank(url)) return;
            if (util.isBlank(name)) {
                name = $(element).text();
                if (util.isBlank(name)) {
                    name = '修改数据';
                }
            }
            app.openPage(name, url);
            // 回调函数
            if (util.isFunction(callback)) {
                callback(res);
            }
        },

        /**
         * 查询数据，一般用于列表页
         *
         * @param element {element} html 元素对象（必要）
         */
        selectData: function (element) {
            let $dataTable = $(element).parents('.e-form').find('.e-datatable');
            if (typeof $dataTable !== 'undefined' && $dataTable.length > 0) {
                $dataTable.EDataTable().reload();
            }
        },

        /**
         * 初始化DataTable，文档请前往[DataTable](http://www.easy-frame.top/guide/plugins/table/table.html)查看
         *
         * @param options {object} 配置（必要）
         * @returns {*|jQuery}
         */
        initDataTable: function (options) {
            // 检查&获取请求地址
            let url = options.url;
            if (util.isBlank(url)) {
                url = getUrl(options.url, 'select', null);
                delete options['url'];
                if (util.isBlank(url)) return;
            }

            /**
             * 默认设置
             */
            let _defaultOptions = {
                selector: '.e-datatable',
                // 数据源
                data: {
                    type: 'remote',
                    source: {
                        autoQuery: true, // 带入表单参数
                        read: {
                            url: url,
                            map: function (res) {
                                if (typeof res.data.records !== 'undefined') { // 带有分页信息
                                    return res.data.records;
                                } else {
                                    return res.data;
                                }
                            }
                        }
                    },
                    saveState: {
                        // 使用cookie/webstorage 保存表格状态(分页, 筛选, 排序)
                        cookie: false,
                        webstorage: true
                    },
                    pageSize: EDefaultOptions.dataTable.page.size, // 页大小
                    serverPaging: true, // 在服务器进行数据分页
                    serverFiltering: true, // 在服务器进行数据过滤
                    serverSorting: true // 在服务器进行数据排序
                },
                toolbar: {
                    items: {
                        pagination: {
                            pagination: [10, 15, 20, 30, 50, 100, -1]
                        }
                    }
                },
                // 布局
                layout: {
                    theme: 'default', // 主题
                    class: '', // 自定义class
                    scroll: true, // 启用滚动条
                    height: EDefaultOptions.dataTable.layout.height, // 高度
                    footer: false // 显示/隐藏 footer
                },
                search: {
                    // 查询条件(仅用于数据在local)
                    input: '.query-modular input, .query-modular select',
                    // 在输入框按回车查询
                    onEnter: true
                },
                // 列滚动
                sortable: true,
                // 分页
                pagination: true
            };
            // 合并配置
            options = $.extend(true, {}, _defaultOptions, options);

            let eDataTable = $(options.selector).EDataTable(options);
            let $form = $(options.selector).parents('form.e-form');
            if (typeof $form !== 'undefined' && $form.length > 0) {
                // 如果有查询按钮,绑定点击重新加载数据事件
                let $searchBtn = $form.find('.btn-search');
                if (typeof $searchBtn !== 'undefined' && $searchBtn.length > 0) {
                    $searchBtn.click(function () {
                        // 查询并返回第一页
                        eDataTable.gotoPage(1);
                    });
                }
                // 如果有重置按钮,绑定点击重置事件
                let $resetBtn = $form.find('.btn-reset');
                if (typeof $resetBtn !== 'undefined' && $resetBtn.length > 0) {
                    $resetBtn.click(function () {
                        $form.resetForm();
                        let $selectPicker = $form.find('.select-picker');
                        if (typeof $selectPicker !== 'undefined' && $selectPicker.length > 0) {
                            $selectPicker.trigger("change");
                        }
                    });
                }

                // 绑定表格工具事件
                // 恢复默认排序
                $form.find('.e-default-order').click(function (e) {
                    e.preventDefault();
                    eDataTable.recoveryDefaultOrder();
                });
                // 恢复默认页大小
                $form.find('.e-default-page-size').click(function (e) {
                    e.preventDefault();
                    eDataTable.recoveryDefaultPageSize();
                });
                // 全部恢复全部
                $form.find('.e-default-all').click(function (e) {
                    e.preventDefault();
                    eDataTable.recoveryDefaultAll();
                });
            }

            return eDataTable;
        },

        /**
         * 将表单数据序列化为json对象
         *
         * @param $form {jQuery} 表单（必要）
         * @returns {null|object} eg: {a: 1, b: 2}
         */
        queryParams: function ($form) {
            let data = $form.serializeArray();
            if (typeof data !== 'undefined' && data.length > 0) {
                let params = {};
                for (let i = 0; i < data.length; i++) {
                    if (util.isNotBlank(data[i].value)) {
                        if (util.isNotBlank(params[data[i].name])) {
                            params[data[i].name] = params[data[i].name] + ',' + data[i].value;
                        } else {
                            params[data[i].name] = data[i].value;
                        }
                    }
                }
                return params;
            } else {
                return null;
            }
        },

        /******************** 提示 ********************/
        /**
         * `info` 提示，
         * 会根据用户偏好设置中设置的提示方式进行提示
         *
         * @param title {string} 标题（必要）
         * @param subtitle {string} 副标题
         */
        infoTip: function (title, subtitle) {
            if (useSimpleTip()) {
                util.toastr({
                    type: 'info',
                    title: title,
                    subtitle: subtitle
                });
            } else {
                util.alertInfo(title, subtitle);
            }
        },

        /**
         * `success` 提示，
         * 会根据用户偏好设置中设置的提示方式进行提示
         *
         * @param title {string} 标题（必要）
         * @param subtitle {string} 副标题
         */
        successTip: function (title, subtitle) {
            if (useSimpleTip()) {
                util.toastr({
                    type: 'success',
                    title: title,
                    subtitle: subtitle
                });
            } else {
                util.alertSuccess(title, subtitle);
            }
        },
        /**
         * `warning`提示，
         * 会根据用户偏好设置中设置的提示方式进行提示
         *
         * @param title {string} 标题（必要）
         * @param subtitle {string} 副标题
         */
        warnTip: function (title, subtitle) {
            if (useSimpleTip()) {
                util.toastr({
                    type: 'warning',
                    title: title,
                    subtitle: subtitle
                });
            } else {
                util.alertWarning(title, subtitle);
            }
        },
        /**
         * `error`提示，
         * 会根据用户偏好设置中设置的提示方式进行提示
         *
         * @param title {string} 标题（必要）
         * @param subtitle {string} 副标题
         */
        errorTip: function (title, subtitle) {
            if (useSimpleTip()) {
                util.toastr({
                    type: 'error',
                    title: title,
                    subtitle: subtitle
                });
            } else {
                util.alertError(title, subtitle);
            }
        },

        /******************** 字典 ********************/
        /**
         * 根据字典类型获取字典数组
         *
         * @param dictType {string} 字典类型（必要）
         * @returns {array|null} 如没有返回`null` eg：[{...}, {...}]
         */
        getSysDictArrayByDictType: function (dictType) {
            if (typeof sysDict !== 'undefined' && util.isNotBlank(dictType)) {
                return sysDict[dictType];
            }
            return null;
        },
        /**
         * 根据字典类型获取字典对象
         *
         * @param dictType {string} 字典类型（必要）
         * @returns {object|null} 如没有返回`null` eg：{1 : {...}, 2: {...}}
         */
        getSysDictsObjectByDictType: function (dictType) {
            let dicts = ETool.getSysDictArrayByDictType(dictType);
            if (dicts != null && dicts.length > 0) {
                let dictsObject = {};
                $(dicts).each(function (index, dict) {
                    dictsObject[dict.code] = dict;
                });
                return dictsObject;
            }
            return null;
        },

        /**
         * 根据字典类型与编码获取字典信息
         *
         * @param dictType {string} 字典类型（必要）
         * @param code {string} 代码（必要）
         * @returns {object|null} 字典对象或`null`
         */
        getSysDictObjectByQuery: function (dictType, code) {
            let dicts = ETool.getSysDictArrayByDictType(dictType);
            if (dicts != null && dicts.length > 0) {
                for (let i = 0; i < dicts.length; i++) {
                    if (dicts[i].code == code) {
                        return dicts[i];
                    }
                }
            }
            return null;
        },

        /**
         * 根据字典类型与编码获取字典名称
         *
         * @param dictType {string} 字典类型（必要）
         * @param code {string} 编码（必要）
         * @returns {string|null} 字典名称或`null`
         */
        getSysDictNameByQuery: function (dictType, code) {
            let dict = ETool.getSysDictObjectByQuery(dictType, code);
            if (dict != null) {
                return dict.name;
            }
            return null;
        },

        /**
         * 将字典转为html元素（徽章）
         *
         * @param code {string} 字典编码（必要）
         * @param dict {object} 字典对象（必要）
         * @returns {string} eg: `<span class="xxx">xxx</span>`
         */
        getDictElement: function (code, dict) {
            let codeArray = [];
            if (typeof code === 'number') {
                codeArray.push(code + '')
            }
            let cur_dict = [];
            if(typeof code === 'string'){
                if(code.includes(',')){
                    codeArray = code.split(',')
                }
            }
            if(util.isArray(code)){
                codeArray = code;
            }



            if (cur_dict == null) {
                // 如果没有对应的字典,检查已知字典是否设置了css
                if (dict != null && dict.length > 0 && util.isNotBlank(dict[0].css)) {
                    cur_dict = {
                        css: 'badge badge--success badge--inline badge--pill badge--rounded',
                        name: code
                    }
                }
            }
            if (cur_dict != null) {
                if (util.isNotBlank(cur_dict.css)) {
                    return '<span class="' + cur_dict.css + '">' + cur_dict.name + '</span>';
                } else {
                    return cur_dict.name;
                }
            } else {
                return code;
            }
        },

        /********************
         ** 用户权限
         ********************/
        /**
         * 获取当前登录用户，默认优先从缓存获取，如不希望从缓存中获取可设置`cache: false`
         *
         * @param cache {boolean|null} 是否使用缓存数据 （默认：true）
         * @return {Object} 当前登录用户信息
         */
        getUser: function (cache) {
            /**
             * 从后端获取当前登录用户
             *
             * @returns {*}
             */
            let _getUser = function () {
                let data = {};

                /**
                 * 将attr:attr数组转为对象
                 * @param data
                 * @returns {object}
                 */
                let arrayToObject = function (data) {
                    let obj = {};
                    if (util.isArray(data)) {
                        $(data).each(function (i, _obj) {
                            let levels = _obj.split(':'), _i = 0;

                            function createLevel(child) {
                                let name = levels[_i++];
                                if (typeof child[name] !== 'undefined' && child[name] !== null) {
                                    if (typeof child[name] !== 'object') {
                                        child[name] = {};
                                    }
                                } else {
                                    child[name] = {};
                                }
                                if (_i === levels.length) {
                                    child[name] = true;
                                } else {
                                    createLevel(child[name]);
                                }
                            }

                            createLevel(obj);
                        });
                        return obj;
                    } else {
                        return null;
                    }
                };

                util.ajax({
                    async: false,
                    url: basePath + '/auth/sys/user/current',
                    // url: basePath + '/assets/data/user.json',
                    type: 'get',
                    success: function (res) {
                        data = res.data;
                    }
                });
                if (typeof data.roleList !== 'undefined') {
                    data.role = arrayToObject(data.roleList);
                }
                if (typeof data.permissionList !== 'undefined') {
                    data.permissions = arrayToObject(data.permissionList);
                }
                return data;
            };

            let user = null;
            if (typeof cache === 'undefined' || cache) {
                user = ETool.getCache(EDefaultOptions.currentUser);
                if (user == null) {
                    user = _getUser();
                    ETool.setCache(EDefaultOptions.currentUser, user);
                } else {
                    user = $.parseJSON(user);
                }
            } else {
                user = _getUser();
                ETool.setCache(EDefaultOptions.currentUser, user);
            }
            return user;
        },

        /**
         * 当前登录用户是否拥有指定权限标识
         *
         * @param code {string} 权限标识（必要）
         * @return {boolean} true/false
         */
        hasPermissions: function (code) {
            let user = ETool.getUser(true);
            return ETool.checkPermissions(code, user.permissions);
        },
        /**
         * 当前登录用户是否没有指定权限标识
         *
         * @param code {string} 权限标识（必要）
         * @return {boolean} true/false
         */
        notHasPermissions: function (code) {
            return !ETool.hasPermissions(code);
        },
        /**
         * 当前登录用户是否属于指定角色标识
         *
         * @param code {string} 角色标识（必要）
         * @return {boolean} true/false
         */
        hasRole: function (code) {
            let user = ETool.getUser(true);
            return ETool.checkPermissions(code, user.role);
        },
        /**
         * 当前登录用户是否不属于指定角色标识
         *
         * @param code {string} 角色标识（必要）
         * @return {boolean} true/false
         */
        notHasRole: function (code) {
            return !ETool.hasRole(code);
        },
        /**
         * 检查权限
         *
         * @param code {string} 权限标识（必要）
         * @param permissions {object} 权限对象（必要）
         * @return {boolean} true/false
         */
        checkPermissions: function (code, permissions) {
            if (util.isNotBlank(code) && permissions != null && typeof permissions === 'object') {
                return Boolean(ETool.getObject(code, permissions, ':'));
            }
            return false;
        },
        /**
         * 获取cookies/localStorage中的对象
         *
         * @param key {string} key（必要）
         * @return {object} value
         */
        getCache: function (key) {
            let obj;
            if (localStorage) {
                obj = localStorage.getItem(key);
            }
            if (obj == null) {
                obj = Cookies.get(key);
            }
            return obj;
        },
        /**
         * 设置cookies/localStorage中的对象
         *
         * @param key {string} key（必要）
         * @param value {object} value（必要）
         */
        setCache: function (key, value) {
            if (util.isNotBlank(key)) {
                if (typeof value === 'object') {
                    value = JSON.stringify(value);
                }
            }
            if (localStorage) {
                localStorage.setItem(key, value);
            }
            Cookies.set(key, value);
        },

        /**
         * 移除指定cookies/localStorage中的对象
         *
         * @param key {string} key（必要）
         */
        cacheRemove: function (key) {
            if (localStorage) {
                localStorage.removeItem(key);
            }
            Cookies.remove(key);
        },
        /********************  工具  *********************/
        /**
         * 根据属性路径获取object中的value
         *
         * @param path {string} 属性路径 eg：`user.depart.name`（必要）
         * @param object {object} 对象（必要）
         * @param separate {string|null} 分隔符（默认：.）
         * @returns {object|null} 如果未找到返回`null`
         */
        getObject: function (path, object, separate) {
            if (util.isBlank(separate)) {
                separate = '.';
            }
            return path.split(separate).reduce(function (obj, i) {
                return obj !== null && typeof obj[i] !== 'undefined' ? obj[i] : null;
            }, object);
        },
        /**
         * 获取操作按钮class
         *
         * @param type {string} 按钮类型（必要）
         * @returns {string}
         */
        getActionsBtnClass: function (type) {
            return getActionsBtnClass(type);
        },
        /**
         * 下载文件
         *
         * @param url {string} 下载地址（必要）
         */
        downloadFile: function (url) {
            let form = document.createElement('form');
            form.setAttribute('action', url);
            form.setAttribute('method', 'post');
            form.setAttribute('style', 'display:none');
            document.body.appendChild(form);
            form.submit();
            document.body.removeChild(form);
        },
        /**
         * 解析响应码，响应码规则请参考[响应码](/guide/standard.html#%E5%93%8D%E5%BA%94%E7%A0%81)
         *
         * @param code {string} 响应码（必要）
         * @returns {{modular: string, code: string, level: string} | string}
         */
        analysisCode: function (code) {
            let result = code;
            // 响应码必须为`resultCode.length`位字符串，如果不是则直接返回传入值
            if (util.isNotBlank(code) && code.length === resultCode.length) {
                result = {
                    // 级别
                    level: code.substr(0, 1),
                    // 模块代码
                    modular: code.substr(1, 2),
                    // 错误代码
                    code: code.substr(3, 3)
                };
            }
            return result;
        },
        ACTIONS_INFO: getActionsBtnClass('info'),
        ACTIONS_SUCCESS: getActionsBtnClass('success'),
        ACTIONS_WARN: getActionsBtnClass('warning'),
        ACTIONS_DANGER: getActionsBtnClass('danger'),
        /******************** jsTree ********************/

        /**
         * 保存/修改jsTree的节点信息
         *
         * @param tree {object|string} 选择器或者jsTree对象（必要）
         * @param node {object} 节点信息（必要）
         */
        saveNode: function (tree, node) {
            tree = ETool.getTree(tree);
            let _node = tree.get_node(node.id, false);
            if (_node != null && _node) { // 节点存在, 更新节点名称、图标
                if (util.isString(node.type)) {
                    tree.set_type(_node, node.type);
                }
                if (util.isString(node.text)) {
                    tree.rename_node(_node, node.text);
                }
                if (util.isString(node.icon)) {
                    tree.set_icon(_node, node.icon);
                }
            } else {
                let pNode = tree.get_node(node.pId, false); // 查找父节点
                if (tree.is_open(pNode) || tree.is_leaf(pNode)) {// 父节点已展开并且没有子节点
                    tree.create_node(pNode, node);//创建节点
                    if (!tree.is_open(pNode)) { // 如果节点没展开,则展开
                        tree.open_node(pNode);
                    }
                } else {
                    tree.open_node(pNode); // 展开父节点,异步加载数据
                }
            }
        },
        /**
         * 删除jsTree的节点
         *
         * @param tree {object|string} 选择器或者jsTree对象（必要）
         * @param ids {number|string} 要删除的id（必要）
         */
        deleteNode: function (tree, ids) {
            tree = ETool.getTree(tree);
            if (util.isNumber(ids)) {
                tree.delete_node(tree.get_node(ids, false));
            } else if (util.isString(ids)) {
                ETool._deleteNode(tree, ids.split(','));
            } else if (util.isArray(ids)) {
                ETool._deleteNode(tree, ids);
            }
        },
        /**
         * 删除jsTree的指定节点
         * @param tree {object|string} 选择器或者jsTree对象（必要）
         * @param ids {array} 要删除的节点id（必要）
         */
        _deleteNode: function (tree, ids) {
            $(ids).each(function (i, id) {
                tree.delete_node(tree.get_node(id, false));
            });
        },
        /**
         * 右键点击时获取用户想操作的jsTree节点 <br/>
         * 1.右键点击的节点属于多选节点, 返回所有已选中节点 <br/>
         * 2.右键点击的节点不属于多选的节点, 返回右键点击节点并选中 <br/>
         * @param data {object}（必要）
         */
        getOperationNodes: function (data) {
            let tree = $.jstree.reference(data.reference);
            let cur_click = tree.get_node(data.reference);
            let selectNodes = tree.get_selected();
            for (let i = 0; i < selectNodes.length; i++) {
                if (selectNodes[i] == cur_click.id) {
                    return selectNodes;
                }
            }
            tree.deselect_all();
            tree.select_node(cur_click);
            return [cur_click.id];
        },
        /**
         * 获取右键点击的jsTree节点
         * @param data {object}（必要）
         * @returns {*|Object|jQuery|void}
         */
        getClickNode: function (data) {
            let tree = $.jstree.reference(data.reference);
            return tree.get_node(data.reference);
        },
        /**
         * 获取jsTree选中节点
         * 注: id='#' 节点会被过滤
         *
         * @param tree {object|string} 选择器或者jsTree对象（必要）
         * @param attr 要获取的属性（默认：返回节点全部信息）
         * @returns {array}
         */
        getCheckedNodes: function (tree, attr) {
            tree = ETool.getTree(tree);
            let checked = [];
            for (let node in tree._model.data) {
                if (tree.is_undetermined(node) || tree.is_checked(node)) {
                    if (typeof tree._model.data[node]['id'] === 'undefined' || tree._model.data[node]['id'] != '#') {
                        checked.push(util.isNotBlank(attr) ? tree._model.data[node][attr] : tree._model.data[node]);
                    }
                }
            }
            return checked;
        },
        /**
         * jsTree 设置节点选中
         *
         * @param tree {object|string} 选择器或者jsTree对象（必要）
         * @param values {array|string} 选中的值,数组或字符串(1,2,3)（必要）
         */
        checkNodes: function (tree, values) {
            tree = ETool.getTree(tree);
            // 暂时禁用级联,防止选中父节点后全选子节点
            let cascade = tree.settings.checkbox.cascade;
            tree.settings.checkbox.cascade = '';
            if (typeof values === 'string') {
                values = values.split(',');
            }
            tree.check_node(values);
            // 恢复级联
            tree.settings.checkbox.cascade = cascade;
        },
        /**
         * jsTree 全选
         *
         * @param tree {object|string} 选择器或者jsTree对象（必要）
         */
        checkAll: function (tree) {
            tree = ETool.getTree(tree);
            tree.check_all();
        },
        /**
         * jsTree 全不选
         *
         * @param tree {object|string} 选择器或者jsTree对象（必要）
         */
        unCheckAll: function (tree) {
            tree = ETool.getTree(tree);
            tree.uncheck_all();
        },
        /**
         * 获取jsTree对象
         *
         * @param tree {object|string} 选择器或者jsTree对象（必要）
         * @returns {object}
         */
        getTree: function (tree) {
            if (typeof tree === 'string') {
                tree = $(tree).jstree(true);
            }
            return tree;
        },

        /**
         * 获取勾选的数据
         *
         * @param $dataTable {object} dataTable 对象（必要）
         * @returns {Array} eg：[1,2,3]
         */
        getSelectData: function ($dataTable) {
            return $dataTable.EDataTable().getValue();
        },
        /**
         * 检查ids是否为空
         *
         * @param ids {array} ids（必要）
         * @param tip {boolean} 是否需要弹出提示`commonTips.noIds`；（默认`false`）
         * @returns {boolean} true/false
         */
        checkSelectDataIsNotEmpty: function (ids, tip) {
            if (ids == null || ids.length === 0) {
                if (tip) {
                    ETool.warnTip(commonTips.fail, commonTips.noIds);
                }
                return false;
            } else {
                return true;
            }
        },
    };
}();
ETool.commonDict = ETool.getSysDictsObjectByDictType('commonStatus');
window.EUtil = EUtil;
